package site.jlopen.service.imp;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;

import site.jlopen.assets.spring.ComponentsInit;
import site.jlopen.components.entity.GraphJson.GraphJsonNode;
import site.jlopen.components.entity.GraphJsonUtil;
import site.jlopen.components.entity.GraphNodeAttr;
import site.jlopen.components.entity.GraphNodeParam;
import site.jlopen.components.entity.GraphNodeParamCopy;
import site.jlopen.domain.job.KusciaJobResult;
import site.jlopen.domain.project.KusciaProjectGraphParam;
import site.jlopen.domain.project.event.ProjectInviteNodeVO;
import site.jlopen.kuscia.model.job.TaskInfo;
import site.jlopen.kuscia.model.task.TaskInputConfig;
import site.jlopen.kuscia.model.task.param.SfClusterDesc;
import site.jlopen.kuscia.model.task.param.SfDatasourceConfig;
import site.jlopen.kuscia.model.task.param.SfNodeEvalParam;
import site.jlopen.kuscia.model.task.param.clusterDevices.SfClusterDescDevices;
import site.jlopen.mapper.node.KusciaNodeMapper;
import site.jlopen.mapper.project.KusciaProjectFlowMapper;
import site.jlopen.mapper.project.KusciaProjectGraphParamMapper;
import site.jlopen.service.intf.project.JobResultService;
import site.jlopen.utils.StringUtil;

@Service
public class JobTaskConvert {
	private static Logger logger = LoggerFactory.getLogger(JobTaskConvert.class);
	@Autowired
	private KusciaNodeMapper nodeMapper;
	@Autowired
	private KusciaProjectFlowMapper flowMapper;
	@Autowired
	private KusciaProjectGraphParamMapper graphParamMapper;
	@Autowired
	private ComponentsInit componentsInit;
	@Autowired 
	public JobResultService resultService;

	public TaskInfo toConvert(GraphJsonUtil graphUtil, Long projectId, Long flowId, Long dataSourceId, String taskId, String taskName, String graphNodeId,
			List<ProjectInviteNodeVO> invites, List<String> dependencies, Map<String, String> newIdMap) throws Exception {
		/*List<TaskPartie> parties = new ArrayList<TaskPartie>();
		for (ProjectInviteNode invite : invites) {
			parties.add(new TaskPartie(invite.getNodeCode(), ""));
		}*/
		if(null == dependencies) {
			dependencies = new ArrayList<String>();
		}
		
		TaskInputConfig config = new TaskInputConfig();
		for (ProjectInviteNodeVO invite : invites) {
			config.addDatasourceConfig(invite.getNodeCode(), new SfDatasourceConfig(invite.getDsId()));
		}
		
		SfClusterDesc clusterDesc = new SfClusterDesc();
		SfClusterDescDevices spu = new SfClusterDescDevices().spu();
		SfClusterDescDevices heu = new SfClusterDescDevices().heu();
		for (ProjectInviteNodeVO invite : invites) {
			spu.addPartie(invite.getNodeCode());
			heu.addPartie(invite.getNodeCode());
		}
		clusterDesc.addDevice(spu);
		clusterDesc.addDevice(heu);
		
		for (ProjectInviteNodeVO invite : invites) {
			clusterDesc.addPartie(invite.getNodeCode());
		}
		clusterDesc.addMapConfig("cross_silo_comm_backend",  "brpc_link");
		config.addClusterDesc(clusterDesc);

		
		GraphJsonNode graphNode = graphUtil.getNodeById(graphNodeId);
		KusciaProjectGraphParam paramInfo = graphParamMapper.selectByInfo(
				new KusciaProjectGraphParam().setParamFlowId(flowId).setParamGraphId(graphNodeId));
		if(null == paramInfo) {
			throw new Exception(graphNode.getData().getLabel() +  "节点参数未配置");
		}
		Map<String, Object> attrsMap = JSON.parseObject(paramInfo.getParamAttr(), new TypeReference<Map<String, Object>>() {});
		
		GraphNodeParam defParam = componentsInit.getNode(graphNode.getData().getId());
		GraphNodeParam param = new GraphNodeParamCopy().init(defParam);
		SfNodeEvalParam nodeEvalParam = new SfNodeEvalParam(param.getDomain(), param.getCode(),  param.getVersion());
		 
		for(GraphNodeAttr attr: param.getAttrs()) {
			if(null == attrsMap.get(attr.getCode())) {
				continue;
			}
			String codeVal  = attrsMap.get(attr.getCode()).toString();
			if(null != codeVal) {
				attr.setProp(codeVal);
				nodeEvalParam.addAttPath(attr.getCode());
				if("ss".equals(attr.getType())) {
					String[] va = codeVal.split(",");
					nodeEvalParam.addAttr(attr.getType(), va);
				}
				else if("b".equals(attr.getType())) {
					nodeEvalParam.addAttr(attr.getType(), "True".equals(codeVal)?true:false);
				}
				else if(attr.getType().startsWith("i")) {
					nodeEvalParam.addAttr(attr.getType(), toInt(codeVal));
				} else {
					nodeEvalParam.addAttr(attr.getType(), codeVal);
				}
			}
		}
		
		config.addNodeEvalParam(nodeEvalParam);
		
		List<String> depsNotReadData = new ArrayList<String>();
		for (String dependencieId : dependencies) {
			KusciaProjectGraphParam dependencieNode = graphParamMapper.selectByInfo(
					new KusciaProjectGraphParam().setParamFlowId(flowId).setParamGraphId(dependencieId));
			if(null == dependencieNode) {
				throw new Exception(graphNode.getData().getLabel() +  "节点上游参数未配置");
			}
			GraphJsonNode dependencieJsonNode = graphUtil.getNodeById(dependencieId);
			if(!"read_data".equals(dependencieJsonNode.getData().getId())) {
				
				depsNotReadData.add(newIdMap.get(dependencieId));
			}
			List<String> dependencieOutds = JSON.parseObject(dependencieNode.getParamOutputs(), new TypeReference<List<String>>() {});
			for (String outId : dependencieOutds) {
				config.addInputId(outId);
			}
		}
		List<String> dependencieOutds = JSON.parseObject(paramInfo.getParamOutputs(), new TypeReference<List<String>>() {});
		for (String outId : dependencieOutds) {
			config.addOutput(outId + ".csv", outId);
			
			KusciaJobResult result = new KusciaJobResult();
			result.setResultProjectId(projectId);
			result.setResultFlowId(flowId);
			result.setResultTaskId(newIdMap.get(taskId));
			result.setResultDataSourceId(dataSourceId);
			result.setResultName(outId + ".csv");
			result.setResultType("REPORT");
			result.setResultGraphId(graphNodeId);
			result.setResultGraphCode(param.getCode());
			result.setResultDomaindataId(outId);
			resultService.saveResult(result);
		}
		
		String taskInputConfig = JSON.toJSONString(config);
		//logger.error("taskInputConfig: {}", taskInputConfig);
		return new TaskInfo(newIdMap.get(taskId), newIdMap.get(taskName), depsNotReadData, taskInputConfig);
	}
	
	private long toInt(String value) {
		try {
			return Long.valueOf(value);
		} catch (Exception e) {
			logger.error("将{}字符串转成long类型的时候出现异常:{}", value, e);
			return 0L;
		}
	}
}
